<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/5/11
 * Time: 17:38
 */

namespace App\Service\Payment;

use App\Common\Fun;
use App\Common\Str;

class WeixinService
{
    /**
     * @param array $orderArr
     * 微信统一下单处理
     */
    public static function unifiedOrder($orderArr = array())
    {
        $wx_config = config('payment.weixin');

        if (!isset($orderArr['order_id'])) {
            return false;
        }

        $order_arr = array(
            'appid' => $wx_config['appid'],
            'mch_id' => $wx_config['mch_id'],
            'nonce_str' => Str::randString(16,2),
            'body' => $wx_config['body'],
            'out_trade_no' => $orderArr['order_id'],
            'total_fee' => $orderArr['price']*100,
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
            'notify_url' => $wx_config['notify_url'],
            'trade_type' => 'JSAPI',
            'openid' => $orderArr['open_id'],
            'time_start' => date('YmdHis',time()), //开始时间
            'time_expire' => date('YmdHis',(time()+60)) //失效时间
        );

        $order_arr['sign'] = self::generateSign($order_arr,$wx_config['key']);

        $xml = self::arrayToXml($order_arr);
        $res = Fun::sendUrl('post',$wx_config['unified_url'],$xml,'xml');

        $res = self::xmlToArray($res);

        if(!$res || $res['return_code'] == 'FAIL' || !isset($res['prepay_id'])){
            return false;
        } else{
            $return_arr['appId'] = $wx_config['appid'];
            $return_arr['nonceStr'] = $order_arr['nonce_str'];
            $return_arr['package'] = "prepay_id={$res['prepay_id']}";
            $return_arr['signType'] = 'MD5';
            $return_arr['timeStamp'] = (string)time();
            $return_arr['sign'] = self::generateSign($return_arr,$wx_config['key']);
            $return_arr['prepay_id'] = $res['prepay_id'];
            return $return_arr;
        }

    }


    /**
     * 生成随机签名算法
     */
    public static function generateSign($order_arr,$key = '')
    {
        ksort($order_arr);
        $string = self::toUrlParam($order_arr);
        $string = $string . "&key=" . $key;
        $string = md5($string);
        $result = strtoupper($string);
        return $result;
    }

    /**
     * 格式化参数格式化成url参数
     */
    public static function toUrlParam($order_arr)
    {
        $buff = "";
        foreach ($order_arr as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }

    /**
     * array to xml
     */
    public static function arrayToXml($params = [])
    {
        if (!is_array($params) || count($params) <= 0) {
            throw new \Exception("数组数据异常！");
        }

        $xml = "<xml>";
        foreach ($params as $key => $val) {
            if (is_numeric($val)) {
                $xml .= ("<" . $key . ">" . $val . "</" . $key . ">");
            } else {
                $xml .= ("<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">");
            }
        }

        $xml .= "</xml>";

        return $xml;
    }



    /**
     * xml to array
     */
    public static function xmlToArray($xml = '')
    {
        libxml_disable_entity_loader(true);
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }

    /**
     * 查询微信订单状态
     */
    public static function orderQuery($out_trade_no)
    {
        $wx_config = config('payment.weixin'); //微信支付参数
        $url = "https://api.mch.weixin.qq.com/pay/orderquery";
        //检测必填参数
        $order_arr = array(
            'out_trade_no' => $out_trade_no,
            'appid' => $wx_config['appid'],
            'mch_id' => $wx_config['mch_id'],
            'nonce_str' => Str::randString(16,2)
        );
        $order_arr['sign'] = self::generateSign($order_arr,$wx_config['key']);

        $xml = self::arrayToXml($order_arr);
        $res = Fun::sendUrl('post',$url,$xml);

        $res = self::xmlToArray($res);

        return $res;
    }

}